package com.xw.musicplayer;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;

import com.xw.musicplayer.bean.Music;
import com.xw.musicplayer.listener.IOnBufferingListener;
import com.xw.musicplayer.listener.IOnMusicChangeListener;
import com.xw.musicplayer.listener.IOnStatusChangeListener;
import com.xw.musicplayer.listener.IOnStopServiceListener;
import com.xw.musicplayer.listener.OnBufferingListener;
import com.xw.musicplayer.listener.OnMusicChangeListener;
import com.xw.musicplayer.listener.OnMusicClickListener;
import com.xw.musicplayer.listener.OnProgressListener;
import com.xw.musicplayer.listener.OnStatusChangeListener;
import com.xw.musicplayer.utils.NotificationUtils;
import com.xw.musicplayer.utils.PlayStatus;

import java.util.ArrayList;
import java.util.List;

public abstract class BaseMusicPlayer {

    private static final int MESSAGE_UPDATE_PROGRESS = 1;
    private static final long UPDATE_TIME = 1000;

    protected Context mContext;
    private ServiceConnection mConnection;
    private IMusicPlayerBridge mBridge;

    private Handler mHandler;
    private List<Music> mMusicList;
    private Runnable mDelayTask;
    private boolean mNeedSynchronizedData;
    private String mMusicListId;
    private boolean mRequestNotification;

    private OnInnerStopListener mOnInnerStopListener;
    private OnInnerBufferingListener mOnInnerBufferingListener;
    private OnInnereStatusChangeListener mOnInnerStatusListener;
    private OnInnerMusicChangeListener mOnInnerMusicChangeListener;

    private List<OnStatusChangeListener> mOnStatusChangeListenerList = new ArrayList<>();
    private List<OnMusicChangeListener> mOnMusicChangeListenerList = new ArrayList<>();
    private List<OnBufferingListener> mOnBufferingListenerList = new ArrayList<>();
    private List<OnProgressListener> mOnProgressListenerList = new ArrayList<>();
    private List<OnMusicClickListener> mOnMusicClickListenerList = new ArrayList<>();

    private Handler mProgressHandler = new Handler(Looper.getMainLooper(), msg -> {

        if (msg.what == MESSAGE_UPDATE_PROGRESS) {
            notifyProgress();
        }

        return true;
    });

    public BaseMusicPlayer(Context mContext) {
        this.mContext = mContext.getApplicationContext();

        mHandler = new Handler(Looper.getMainLooper());
        mMusicList = new ArrayList<>();

        mOnInnerStopListener = new OnInnerStopListener();
        mOnInnerBufferingListener = new OnInnerBufferingListener();
        mOnInnerMusicChangeListener = new OnInnerMusicChangeListener();
        mOnInnerStatusListener = new OnInnereStatusChangeListener();

        if (isServiceRuning() && mBridge == null) {
            oCreateNeedConnect();
        }
    }

    /**
     * 播放服务正在运行，建立连接
     */
    private void oCreateNeedConnect() {
        mNeedSynchronizedData = true;
        startPlayerService();
    }

    /**
     * 绑定播放服务
     */
    protected void startPlayerService() {
        //bind方式当连接失败时就自动销毁,所以双启动让service常驻
        mConnection = new MusicSerciceConnection();
        Intent intent = new Intent(mContext, MusicServer.class);
        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mContext.startForegroundService(intent);
        } else {
            mContext.startService(intent);
        }
    }

    /**
     * 解绑播放服务
     */
    protected void stopBindPlayService() {
        mHandler.post(() -> notifyStatus(PlayStatus.STATE_RELEASE));

        unregisterListener();
        if (mBridge != null) {
            Intent intent = new Intent(mContext,MusicServer.class);
            if (mConnection != null) {
                mContext.unbindService(mConnection);
            }

            mContext.stopService(intent);
        }

        removeMessage();
        mBridge = null;
        mConnection = null;
        mDelayTask = null;
        mNeedSynchronizedData = false;
    }

    /**
     * 关闭播放服务
     */
    public void closePlayService() {
        stopBindPlayService();
    }

    /**
     * 是否请求通知权限
     */
    public boolean requestNotification() {
        if (!NotificationUtils.isNotifyEnabled(mContext) && !mRequestNotification) {
            mRequestNotification = true;
            NotificationUtils.toSetting(mContext);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 播放服务是否已经启动了
     *
     * @return true启动了播放服务, false则没有
     */
    public boolean isRunningPlayService() {
        return isServiceRuning();
    }

    /**
     * 加载播放列表.
     */
    public void setMusicList(List<Music> musicList) {
        setMusicList(null,musicList);
    }

    /**
     * 设置一个播放列表,并为该列表设置一个id,该id可以用作判断列表来源.在多列表,多监听场景推荐使用该方法.
     */
    public void setMusicList(String musicId,List<Music> musicList) {
        if (musicList == null || musicList.isEmpty()) {
            return;
        }

        mMusicListId = musicId;
        mMusicList.clear();
        mMusicList.addAll(musicList);
        if (mBridge != null) {
            setListInner();
        }
    }

    private void setListInner() {
        if (mBridge != null && !mMusicList.isEmpty()) {
            try {
                mBridge.setMusicList(mMusicListId, mMusicList);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public Music getMusic(int position) {
        if (position >= 0 && position < mMusicList.size()) {
            return mMusicList.get(position);
        }

        return null;
    }

    /**
     * 获取正在播放的歌曲的索引
     */
    public int getPlayingIndex() {
        if (mBridge != null) {
            try {
                return mBridge.getPlayingIndex();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return 0;
    }

    /**
     * 获取播放队列id
     */
    public String getmMusicListId() {
        return mMusicListId;
    }

    /**
     * 获取播放列表歌曲数量
     */
    public int getMusicCount() {
        return mMusicList.size();
    }

    /**
     * 异步获取播放列表
     * @return
     */
    public List<Music> getmMusicListAsync()  {
        if (mBridge != null) {
            try {
                mMusicListId = mBridge.getMusicListId();
                List<Music> list = mBridge.getMusicList();
                mMusicList.clear();

                if (list != null && !list.isEmpty()) {
                    mMusicList.addAll(list);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return mMusicList;
    }

    /*************************操作*************************/

    /**
     * 开始播放
     */
    public void play() {
        if (mBridge != null) {
            playInner();
        } else {
            Runnable task = this::playInner;
            startPostTask(task);
        }
    }

    private void playInner() {
        if (mBridge != null) {
            try {
                mBridge.play();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 直播播放位置
     * @param position
     */
    public void play(int position) {
        if (mBridge != null) {
            playInner(position);
        } else {
            Runnable task = () -> playInner(position);
            startPostTask(task);
        }
    }

    private void playInner(int posiiont) {
        if (mBridge != null) {
            try {
                mBridge.playIndex(posiiont);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 下一首
     */
    public void playNext() {
        if (mBridge != null) {
            playNextInner();
        } else {
            Runnable task = this::playNextInner;
            startPostTask(task);
        }
    }

    private void playNextInner() {
        if (mBridge != null) {
            try {
                mBridge.playNext();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 上一首
     */
    public void playPrevious() {
        if (mBridge != null) {
            playPreviousInner();
        } else {
            Runnable task = this::playPreviousInner;
            startPostTask(task);
        }
    }

    private void playPreviousInner() {
        try {
            if (mBridge != null) {
                mBridge.playPrevious();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停
     */
    public void pause() {
        if (mBridge != null) {
            pauseInner();
        } else {
            Runnable task = this::pauseInner;
            startPostTask(task);
        }
    }

    private void pauseInner() {
        try {
            if (mBridge != null) {
                mBridge.pause();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置播放进度
     * @param progress [0 - 100]
     */
    public void seek(int progress) {
        try {
            if (mBridge != null) {
                mBridge.setSeek(progress);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取当前播放的进度.
     *
     * @return 毫秒
     */
    public long getCurrentPosition() {
        try {
            if (mBridge != null) {
                return mBridge.getCurrentPosition();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取当前歌曲总时长.
     *
     * @return 总时长毫秒
     */
    public long getDuration() {
        try {
            if (mBridge != null) {
                return mBridge.getDuration();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取当前歌曲缓冲百分比.
     *
     * @return [0, 100]
     */
    public int getBufferedPercentage() {
        try {
            if (mBridge != null) {
                return mBridge.getBufferedPercentage();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取播放状态.
     *
     * @return true正在播放, 反之false
     */
    public boolean isPlaying() {
        try {
            if (mBridge != null) {
                return mBridge.isPlaying();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }

    private void startPostTask(Runnable task) {
        if (mDelayTask != null) {
            mHandler.removeCallbacks(task);
        }

        mDelayTask = task;
        startPlayerService();
    }

    /**************************************************/

    /**
     * 判断服务是否启动
     */
    private boolean isServiceRuning() {

        ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        if (activityManager == null) {
            return false;
        }

        List<ActivityManager.RunningServiceInfo> serviceInfos = activityManager.getRunningServices(Integer.MAX_VALUE);
        if (serviceInfos == null || serviceInfos.isEmpty()) {
            return false;
        }

        boolean isRunning = false;
        for (int i = 0; i < serviceInfos.size(); i++) {
            ActivityManager.RunningServiceInfo info = serviceInfos.get(i);
            if (info != null && info.service.getClassName().contains(MusicServer.class.getName())) {
                isRunning = true;
                break;
            }
        }

        return isRunning;
    }

    /**
     * 监听停止事件
     */
    private class OnInnerStopListener extends IOnStopServiceListener.Stub {

        @Override
        public void onStopService() {
            stopBindPlayService();
        }
    }
    /**
     * 播放状态监听.
     */
    private class OnInnereStatusChangeListener extends IOnStatusChangeListener.Stub {

        @Override
        public void onStatusChange(int status) throws RemoteException {
            mHandler.post(() -> notifyStatus(status));
        }
    }

    /**
     * 歌曲切换状态监听.
     */
    private class OnInnerMusicChangeListener extends IOnMusicChangeListener.Stub {

        @Override
        public void onMusicChange(int newPosition, int oldPosition) throws RemoteException {
            mHandler.post(() -> notifyChange(newPosition, oldPosition));
        }
    }

    /**
     * 缓冲状态监听.
     */
    private class OnInnerBufferingListener extends IOnBufferingListener.Stub {

        @Override
        public void onBufferingStart() throws RemoteException {
            mHandler.post(() -> notifyBuffing(true));
        }

        @Override
        public void onBufferingEnd() throws RemoteException {
            mHandler.post(() -> notifyBuffing(false));
        }
    }

    /**
     * 注册监听
     */
    private void registerListener() {
        if (mBridge != null) {
            try {
                mBridge.registerOnStopListener(mOnInnerStopListener);
                mBridge.registerOnBufferingListener(mOnInnerBufferingListener);
                mBridge.registerOnStatusChangeListener(mOnInnerStatusListener);
                mBridge.registerOnMusicChangeListener(mOnInnerMusicChangeListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 取消注册监听
     */
    private void unregisterListener() {
        if (mBridge != null) {
            try {
                mBridge.unregisterOnStopListener(mOnInnerStopListener);
                mBridge.unregisterOnBufferingListener(mOnInnerBufferingListener);
                mBridge.unregisterOnStatusChangeListener(mOnInnerStatusListener);
                mBridge.unregisterOnMusicChangeListener(mOnInnerMusicChangeListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 更新播放状态
     */
    private void notifyStatus(int newStatus) {
        if (newStatus == PlayStatus.STATE_PLAYING) {
            sendUpdateMessage();
        } else {
            removeMessage();
        }

        for (OnStatusChangeListener listener : mOnStatusChangeListenerList) {
            listener.onStatusChange(newStatus);
        }
    }

    /**
     * 播放歌曲改变
     */
    private void notifyChange(int newPosition,int oldPosition) {
        for (OnMusicChangeListener listener : mOnMusicChangeListenerList) {
            listener.onMusicChange(newPosition, oldPosition);
        }
    }

    private void notifyMusicClick() {
        if (!mOnMusicClickListenerList.isEmpty()) {
            int index = getPlayingIndex();
            Music music = getMusic(index);
            for (OnMusicClickListener listener : mOnMusicClickListenerList) {
                listener.onMusicClick(music,index);
            }
        }
    }

    private void notifyBuffing(boolean start) {
        if (start) {
            for (OnBufferingListener listener : mOnBufferingListenerList) {
                listener.onBufferingStart();
            }
        } else {
            for (OnBufferingListener listener : mOnBufferingListenerList) {
                listener.onBufferingEnd();
            }
        }
    }

    private void notifyProgress() {

        if (!mOnProgressListenerList.isEmpty()) {
            long current = getCurrentPosition();
            long duration = getDuration();
            int percentage = getBufferedPercentage();
            for (OnProgressListener listener : mOnProgressListenerList) {
                listener.onProgress(current,duration,percentage);
            }
        }
        sendUpdateMessage();
    }

    /**
     * 发送更新消息
     */
    private void sendUpdateMessage() {
        mProgressHandler.removeMessages(MESSAGE_UPDATE_PROGRESS);
        if (!mOnProgressListenerList.isEmpty() && mBridge != null) {
            mProgressHandler.sendEmptyMessageDelayed(MESSAGE_UPDATE_PROGRESS,UPDATE_TIME);
        }
    }

    private void removeMessage() {
        mProgressHandler.removeMessages(MESSAGE_UPDATE_PROGRESS);
    }

    /**
     * 远程服务连接
     */
    private class MusicSerciceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBridge = IMusicPlayerBridge.Stub.asInterface(service);
            registerListener();

            if (mNeedSynchronizedData) {
                getmMusicListAsync();
            } else {
                setListInner();
            }

            mNeedSynchronizedData = false;
            if (mDelayTask != null) {
                mHandler.post(mDelayTask);
            }

            mDelayTask = null;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            stopBindPlayService();
        }
    }

    public void registerStatusChangeListener(OnStatusChangeListener listener) {
        if (!mOnStatusChangeListenerList.contains(listener)) {
            mOnStatusChangeListenerList.add(listener);
        }
    }

    public void unregisterStatusChangeListener(OnStatusChangeListener listener) {
        mOnStatusChangeListenerList.remove(listener);
    }

    public void registerMusicChangeListener(OnMusicChangeListener listener) {
        if (!mOnMusicChangeListenerList.contains(listener)) {
            mOnMusicChangeListenerList.add(listener);
        }
    }

    public void unregisterMusicChangeListener(OnMusicChangeListener listener) {
        mOnMusicChangeListenerList.remove(listener);
    }

    public void registerBuffingListener(OnBufferingListener listener) {
        if (!mOnBufferingListenerList.contains(listener)) {
            mOnBufferingListenerList.add(listener);
        }
    }

    public void unregisterBuffingListener(OnBufferingListener listener) {
        mOnBufferingListenerList.remove(listener);
    }

    public void registerProgressListener(OnProgressListener listener) {
        if (!mOnProgressListenerList.contains(listener)) {
            mOnProgressListenerList.add(listener);
            sendUpdateMessage();
        }
    }

    public void unregisterProgressListener(OnProgressListener listener) {
        mOnProgressListenerList.remove(listener);
    }

    public void registerMusicClickListener(OnMusicClickListener listener) {
        if (!mOnMusicClickListenerList.contains(listener)) {
            mOnMusicClickListenerList.add(listener);
            sendUpdateMessage();
        }
    }

    public void unregisterMusicClickListener(OnMusicClickListener listener) {
        mOnMusicClickListenerList.remove(listener);
    }
}
